﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Protocol;
using System.Collections.Concurrent;
using Atom.dao.Model;
using Atom.NetFrame;
using Atom.Tool;

namespace Atom.Logic.Match
{
    public class MatchHandle : AbsOnceHandler, HandleInterface
    {
        /// <summary>
        /// 多线程处理类，防止数据竞争导致脏数据， 使用线程安全字典
        /// 玩家所在匹配房间映射
        /// </summary>
        ConcurrentDictionary<int, int> userRoom = new ConcurrentDictionary<int, int>();

        /// <summary>
        /// 房间ID和房间的映射，等待中的房间
        /// </summary>
        ConcurrentDictionary<int, MatchRoom> roomMap = new ConcurrentDictionary<int, MatchRoom>();

        /// <summary>
        /// 回收利用过的房间对象再次利用，减少gc性能开销
        /// </summary>
        ConcurrentStack<MatchRoom> cache = new ConcurrentStack<MatchRoom>();

        private ConcurrentInteger index = new ConcurrentInteger();


        public void ClientClose(UserToken ut, string error)
        {
            Level(ut);
        }

        public void ClientConnect(UserToken ut)
        {

        }

        public void MessageReceive(UserToken ut, SocketModel message)
        {
            switch (message.Command)
            {
                case MatchProtocol.CREATE_REQ:
                    Create(ut);
                    break;
                case MatchProtocol.MATCH_REQ:
                    Match(ut);
                    break;
                case MatchProtocol.BEGIN_REQ:
                    Begion(ut);
                    break;
                case MatchProtocol.LEVEL_REQ:
                    Level(ut);
                    break;
            }
        }

        /// <summary>
        /// 创建房间
        /// </summary>
        private void Create(UserToken ut)
        {

            ExecutorPool.Instance.Executor(
                delegate
                    {
                        MatchRoom room = new MatchRoom();
                        room.ID = index.GetAndAdd();
                        UserMode mode = UserBiz.GetUser(ut);
                        room.MatserID = mode.ID;
                        room.MaxUser = 3;
                        userRoom.TryAdd(room.MatserID, room.ID);
                        roomMap.TryAdd(room.ID, room);
                        room.Team.Add(mode.ID);

                        SendMsg(ut, MatchProtocol.CREATE_RES, null);
                    }
            );
        }

        /// <summary>
        /// 匹配
        /// </summary>
        /// <param name="ut"></param>
        public void Match(UserToken ut)
        {
            ExecutorPool.Instance.Executor(
                delegate
                {
                    foreach (var item in roomMap)
                    {
                        if (item.Value.Team.Count < item.Value.MaxUser)
                        {
                            UserMode mode = UserBiz.GetUser(ut);
                            item.Value.Team.Add(mode.ID);
                            ResMatchResult result = new ResMatchResult();
                            int[] ids = new int[item.Value.Team.Count];
                            for (int i = 0; i < item.Value.Team.Count; i++)
                            {
                                UserToken utTemp = GetUserToken(item.Value.Team[i]);
                                mode = UserBiz.GetUser(ut);
                                if (utTemp == ut)
                                {
                                    result.Add(mode.ID, mode.Name, true);
                                }
                                else
                                {
                                    result.Add(mode.ID, mode.Name, false);
                                }
                                ids[i] = mode.ID;
                            }
                            SendMsgToUsers(ids, Gettype(), GetArea(), MatchProtocol.MATCH_RES, result.Encode());

                        }
                    }
                }
            );
        }
        /// <summary>
        /// 房主开始战斗
        /// </summary>
        /// <param name="ut"></param>
        public void Begion(UserToken ut)
        {
            ExecutorPool.Instance.Executor(
                delegate
                {
                    int userID = GetUserID(ut);
                    MatchRoom room = null;
                    int roomId = -1;
                    foreach (var item in roomMap)
                    {
                        //必须是房主才能开始
                        if (userID == item.Value.MatserID)
                        {
                            room = item.Value;
                            roomId = item.Key;
                            break;
                        }
                    }
                    if (room != null)
                    {
                        //通知战斗模块，开始战斗
                        EventUtil.CreateFight(room.Team);
                        //移除
                        int outTemp = 0;
                        for (int i = 0; i < room.Team.Count; i++)
                        {
                            userRoom.TryRemove(room.Team[i], out outTemp);
                        }
                        roomMap.TryRemove(roomId, out room);
                    }
                }
            );
        }

        /// <summary>
        /// 离开
        /// </summary>

        private void Level(UserToken ut)
        {
            //用户ID
            int userId = GetUserID(ut);
            //判断用户和房间是否有映射关系，没有则返回
            if (!userRoom.ContainsKey(userId)) return;
            //取出房间ID
            int roomId = userRoom[userId];
            //保险判断
            if (roomMap.ContainsKey(roomId))
            {
                MatchRoom room = roomMap[roomId];
                List<int> levelIds = new List<int>();
                int roomIDTemp;
                if (userId == room.MatserID)
                {
                    //如果是房主，则房间内所有人都离开
                    for (int i = 0; i < room.Team.Count; i++)
                    {
                        userRoom.TryRemove(room.Team[i], out roomIDTemp);
                        levelIds.Add(room.Team[i]);
                    }
                    roomMap.TryRemove(roomId, out room);
                }
                else
                {
                    userRoom.TryRemove(userId, out roomIDTemp);
                    room.Team.Remove(userId);
                    levelIds.Add(userId);
                }
                ResLevelResult result = new ResLevelResult();
                for (int i = 0; i < levelIds.Count; i++)
                {
                    UserToken utTemp = GetUserToken(levelIds[i]);
                    UserMode mode = UserBiz.GetUser(ut);
                    result.Add(mode.ID, mode.Name);
                }
                SendMsgToUsers(levelIds.ToArray(), Gettype(), GetArea(), MatchProtocol.LEVEL_RES, result.Encode());
            }
        }

        public override byte Gettype()
        {
            return GameProtocol.TYPE_MATCH;
        }
        public override int GetArea()
        {
            return 0;
        }
    }
}
